<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Java NIO ByteBuffer flip() Function Explained</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            line-height: 1.6;
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
            color: #333;
        }
        h1 {
            color: #2c3e50;
            border-bottom: 2px solid #3498db;
            padding-bottom: 10px;
        }
        h2 {
            color: #2980b9;
            margin-top: 30px;
        }
        code {
            background-color: #f8f9fa;
            padding: 2px 4px;
            border-radius: 4px;
            font-family: Consolas, monospace;
        }
        pre {
            background-color: #f8f9fa;
            padding: 15px;
            border-radius: 5px;
            overflow-x: auto;
        }
        table {
            width: 100%;
            border-collapse: collapse;
            margin: 20px 0;
        }
        th, td {
            border: 1px solid #ddd;
            padding: 8px;
            text-align: left;
        }
        th {
            background-color: #f2f2f2;
        }
        .note {
            background-color: #e7f5fe;
            border-left: 4px solid #3498db;
            padding: 10px;
            margin: 15px 0;
        }
        .warning {
            background-color: #fff3e0;
            border-left: 4px solid #ffa726;
            padding: 10px;
            margin: 15px 0;
        }
    </style>
</head>
<body>
    <h1>Java NIO ByteBuffer 的 flip() 函数详解</h1>
    
    <p><code>ByteBuffer.flip()</code> 是 Java NIO 中一个关键的操作方法，用于在读写模式之间切换缓冲区。理解这个方法对于正确使用 NIO 进行数据传输至关重要。</p>
    
    <h2>核心作用</h2>
    <p><code>flip()</code> 方法主要完成如下两步：</p>
    <ol>
        <li><strong>将 limit 设置为当前 position 的值</strong></li>
        <li><strong>将 position 重置为 0</strong></li>
    </ol>
    
    <h2>工作原理</h2>
    
    <h3>写模式 → 读模式转换</h3>
    <pre><code>ByteBuffer buffer = ByteBuffer.allocate(1024);

// 写入数据
buffer.put("Hello".getBytes());

// 此时状态:
// position = 5 (写入5个字节后)
// limit = 1024 (初始容量)
// capacity = 1024

buffer.flip(); // 切换到读模式

// flip()后状态:
// position = 0 (准备从头读取)
// limit = 5 (只能读取已写入的5个字节)
// capacity = 1024 (不变)</code></pre>
    
    <h3>内部指针变化图示</h3>
    <pre>写模式:
[0][1][2][3][4][5][...][1023]
 ↑ position=5
           ↑ limit=1024

flip()后读模式:
[0][1][2][3][4][5][...][1023]
 ↑ position=0
     ↑ limit=5</pre>
    
    <h2>典型使用场景</h2>
    
    <p><strong>1. 写入后读取</strong>：</p>
    <pre><code>// 写入数据
buffer.put(data);

// 准备读取
buffer.flip();

// 读取数据
channel.write(buffer);</code></pre>
    
    <p><strong>2. 通道读写</strong>：</p>
    <pre><code>// 从通道读取到缓冲区
channel.read(buffer);
buffer.flip();

// 从缓冲区写入到通道
channel.write(buffer);
buffer.clear(); // 准备下一次读取</code></pre>
    
    <h2>相关方法对比</h2>
    <table>
        <tr>
            <th>方法</th>
            <th>作用</th>
        </tr>
        <tr>
            <td><code>flip()</code></td>
            <td>写→读切换：limit=position, position=0</td>
        </tr>
        <tr>
            <td><code>rewind()</code></td>
            <td>重读：position=0，limit不变</td>
        </tr>
        <tr>
            <td><code>clear()</code></td>
            <td>读→写切换：position=0, limit=capacity</td>
        </tr>
        <tr>
            <td><code>compact()</code></td>
            <td>保留未读数据：将未读数据移到开头，position=剩余数据量，limit=capacity</td>
        </tr>
    </table>
    
    <h2>常见错误</h2>
    <div class="warning">
        <p><strong>1. 忘记调用 flip()</strong>：</p>
        <ul>
            <li>会导致读取不到数据或读取错误数据</li>
        </ul>
        
        <p><strong>2. 错误调用顺序</strong>：</p>
        <pre><code>buffer.flip();
buffer.put(data); // 错误！flip后处于读模式，不能写入</code></pre>
        
        <p><strong>3. 与 clear() 混淆</strong>：</p>
        <ul>
            <li>flip() 用于写后读</li>
            <li>clear() 用于读后写</li>
        </ul>
    </div>
    
    <h2>最佳实践</h2>
    <div class="note">
        <p><strong>1. 遵循固定模式</strong>：</p>
        <pre><code>buffer.clear();    // 准备写入
channel.read(buffer); 
buffer.flip();     // 准备读取
channel.write(buffer);</code></pre>
        
        <p><strong>2. 在调试时检查缓冲区状态</strong>：</p>
        <pre><code>System.out.println("pos=" + buffer.position() + 
                  ", limit=" + buffer.limit() + 
                  ", cap=" + buffer.capacity());</code></pre>
        
        <p><strong>3. 考虑使用工具类方法简化操作</strong>：</p>
        <pre><code>public static void drainBuffer(ByteBuffer buffer, WritableByteChannel channel) 
    throws IOException {
    buffer.flip();
    while (buffer.hasRemaining()) {
        channel.write(buffer);
    }
    buffer.clear();
}</code></pre>
    </div>
    
    <p>理解并正确使用 <code>flip()</code> 方法是掌握 Java NIO 高效数据传输的关键之一。</p>
</body>
</html>